package buffbuildergui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

import java.io.File;

import java.util.ArrayList;

import javax.swing.Action;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

public class EntityPanel extends JPanel implements MouseListener{
    JList propertyList = null;
    ClickScroller propertyScroller = null;
    DefaultListModel propertyData = new DefaultListModel();
    Entity attachedEntity = null;
    JLabel title = null;
    ListAction la = null;
    Action edit = null;
    JButton cmdClose = null;
    JButton cmdMinimize = null;
    Boolean visibleProperties = true;
    int preferredWidth = 285;
    int preferredHeight = 255;
    int preferredMinHeight = 29;
    DefaultListModel plugData = new DefaultListModel();
    ArrayList<EntityPanel> children = new ArrayList<>();
    ArrayList<EntityPanel> parents = new ArrayList<>();
    ArrayList<OutPort> outies = new ArrayList<>();
    ArrayList<Property> virtualList = new ArrayList<>();
    
    public EntityPanel(String name,Entity entityToAttach, EntityPanel par) {
        super();
        setLayout(null);
        if(par != null)
            parents.add(par);
        
        setSize(preferredWidth,preferredHeight);
        
        title = new JLabel();         
        title.setText(name);
        add(title);
        title.setBounds(5,5,200,15);

        attachedEntity = entityToAttach;
        attachedEntity.glueToPanel(this);
        
        cmdMinimize = new JButton();
        cmdMinimize.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                minimize();
            }
        });
        cmdMinimize.setText("");
        cmdMinimize.setBackground(Color.lightGray);
        add(cmdMinimize);
        cmdMinimize.setBounds(240,10,20,10);
        
        cmdClose = new CloseBuff();
        cmdClose.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
                //Execute when button is pressed
                kill(e.getSource());
            }
        });
        cmdClose.setText("");
        cmdClose.setBackground(Color.black);
        add(cmdClose);
        cmdClose.setBounds(260,10,20,10);
        
        propertyList = new ClickList(propertyData);
        propertyList.setBorder(new LineBorder(Color.black,1,false));
        propertyList.setLayoutOrientation(JList.VERTICAL);
        propertyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        propertyList.setVisibleRowCount(-1);
        edit = new EditListAction(false);
        la = new ListAction(propertyList,edit);
        
        propertyScroller = new ClickScroller();
        propertyScroller.setLocation(0,0);
        propertyScroller.setVisible(true);
        propertyScroller.setViewportView(propertyList);
        add(propertyScroller);
        propertyScroller.setBounds(2,26,258,228);
        
        
        populate(propertyData);
        
        
        setBorder(new LineBorder(Color.black,1,false));
        setLocation(100,100);
        addMouseListener(this);
        minimize();
    }
    
    public int convertRowToID(String str) {
        for(int i = 0; i < virtualList.size(); i++) {
            Property p = virtualList.get(i);
            String name = p.getName();
            if(name.equals(str))
                return i;
        }
        return -1;
    }
    
    public void populate(DefaultListModel dlm) {
        dlm.clear();
        virtualList.clear();
        Entity e = attachedEntity;
        if(this instanceof ActionPanel)
            title.setText(e.props.get(0).getValue());
        // iterate through all properties
        for(int i = 0; i < e.props.size(); i++) {
            Property cur = e.props.get(i);
            cur.populate(dlm);
        }
    }
    
    void kill(Object sourceButton) {
        kill(sourceButton, false);
    }
    
    void kill(Object sourceButton, boolean overkill){        
        CloseBuff cb = (CloseBuff)sourceButton;
        EntityPanel ep = (EntityPanel)cb.getParent();
        JLayeredPane jlp = (JLayeredPane)ep.getParent();
        
        for(int i = 0; i < parents.size(); i++) {
            parents.get(i).children.remove(this);
        }
        for(int i = 0; i < children.size(); i++) {
            children.get(i).parents.remove(this);
        }
        for(int i = 0; i < children.size(); i++) {
            if(children.get(i) instanceof ActionPanel/* && this instanceof BuffPanel*/) {
                EntityPanel child = children.get(i);
                jlp.remove(child);
                for(int j = 0; j < child.children.size(); j++) {
                    EntityPanel gc = child.children.get(j);
                    gc.parents.remove(child);
                    child.children.remove(gc);
                    if(gc instanceof ActionPanel)
                    {
                        jlp.remove(gc);
                        for(int k = 0; k < gc.children.size(); k++) {
                            EntityPanel ggc = gc.children.get(k);
                            ggc.parents.remove(gc);
                        }
                    }
                }
            }
        }
        
        //remove reference
        JPanel jp = (JPanel)jlp.getParent();
        JLayeredPane jlp0 = (JLayeredPane)jp.getParent();
        JRootPane jrp = (JRootPane)jlp0.getParent();
        jfMainFrame jfm = (jfMainFrame)jrp.getParent();
        
        if(this instanceof AbilityPanel) {
            int murderIsLegal = -1;
            if(!overkill)
                murderIsLegal = JOptionPane.showConfirmDialog(this,"Are you sure you want to delete Ability" + title.getText() + "? This action cannot be undone.");
            if(murderIsLegal != JOptionPane.YES_OPTION && !overkill) 
                return;
            ArrayList<Ability> al = jfm.abilityList;
            String title = ep.title.getText();
            for(int i = 0; i < al.size(); i++) {
                String name = al.get(i).name;
                if(name.equals(title)) {
                    jfm.abilityList.remove(i);
                }
            }
        }
        else if(this instanceof BuffPanel) {
            int murderIsLegal = -1;
            if(!overkill)
                murderIsLegal = JOptionPane.showConfirmDialog(this,"Are you sure you want to delete Buff" + title.getText() + "? This action cannot be undone.");
            if(murderIsLegal != JOptionPane.YES_OPTION && !overkill) 
                return;
            ArrayList<Buff> bl = jfm.buffList;
            String title = ep.title.getText();
            for(int i = 0; i < bl.size(); i++) {
                String name = bl.get(i).name;
                if(name.equals(title)) {
                    jfm.buffList.remove(i);
                }
            }
            String nam = attachedEntity.name;
            for(int i = 0; i < parents.size(); i++) {
            EntityPanel curPar = parents.get(i);
            for(int j = 0; j < curPar.virtualList.size(); j++) {
                Property curProp = curPar.virtualList.get(j);
                if(curProp.getValue().equals("\"" + nam + "\"")) {
                    curProp.overwrite("\"\"");
                    curPar.populate(curPar.propertyData);
                    break;
                }
            }
        }
        }
        else if(this instanceof ActionPanel){
            ActionPanel ap = (ActionPanel)this;
            String str = "";
            if(attachedEntity instanceof InstantAction)
            {
                EntityPanel parent = ap.parents.get(0);
                if(parent instanceof BuffPanel) {
                    parent.attachedEntity.instant--;
                    str = "numInstantActions";
                    int i = parent.convertRowToID(str);
                    Property target = parents.get(0).virtualList.get(i);
                    target.overwrite(parent.attachedEntity.instant + "");
                    parent.propertyData.set(i,target.stringify());
                    parent.populate(parent.propertyData);
                }
            }
            else if(attachedEntity instanceof PeriodicAction)
            {
                EntityPanel parent = ap.parents.get(0);
                if(parent instanceof BuffPanel) {
                    parent.attachedEntity.periodic--;
                    str = "numPeriodicActions";
                    int index = -1;
                    int i = parent.convertRowToID(str);
                    Property target = parents.get(0).virtualList.get(i);
                    target.overwrite("" + parent.attachedEntity.periodic);
                    parent.propertyData.set(i,target.stringify());
                }
            }
            else if(attachedEntity instanceof OverTimeAction)
            {
                EntityPanel parent = ap.parents.get(0);
                if(parent instanceof BuffPanel) {
                    parent.attachedEntity.over--;
                    str = "numOverTimeActions";
                    int index = -1;
                    int i = parent.convertRowToID(str);
                    Property target = parents.get(0).virtualList.get(i);
                    target.overwrite("" + parent.attachedEntity.over);
                    parent.propertyData.set(i,target.stringify());
                }
            }
            else if(attachedEntity instanceof EntityModifier)
            {
                EntityPanel parent = ap.parents.get(0);
                if(parent instanceof BuffPanel) {
                    parent.attachedEntity.modifiers--;
                    str = "numEntityModifiers";
                    int index = -1;
                    int i = parent.convertRowToID(str);
                    Property target = parents.get(0).virtualList.get(i);
                    target.overwrite("" + parent.attachedEntity.modifiers);
                    parent.propertyData.set(i,target.stringify());
                }
            }
            else if(attachedEntity instanceof EntityBoolModifier)
            {
                EntityPanel parent = ap.parents.get(0);
                if(parent instanceof BuffPanel) {
                    parent.attachedEntity.bools--;
                    str = "numEntityBoolModifiers";
                    int index = -1;
                    int i = parent.convertRowToID(str);
                    Property target = parents.get(0).virtualList.get(i);
                    target.overwrite("" + parent.attachedEntity.bools);
                    parent.propertyData.set(i,target.stringify());
                }
            }
            else if(attachedEntity instanceof FinishCondition)
            {
                EntityPanel parent = ap.parents.get(0);
                if(parent instanceof BuffPanel) {
                    parent.attachedEntity.finishers--;
                    str = "numFinishConditions";
                    int index = -1;
                    int i = parent.convertRowToID(str);
                    Property target = parents.get(0).virtualList.get(i);
                    target.overwrite("" + parent.attachedEntity.finishers);
                    parent.propertyData.set(i,target.stringify());
                }
            }
            // TODO: do the other types as they are added
        }
            
        //cleanup
        jlp.remove(ep);
        jfm.revalidate();
        jfm.repaint();
    }
    String export() {
        return "";
    }
    void demoPrint() {
        JOptionPane.showMessageDialog(this, export());
    }
    void print(File f) {
        
    }
    
    void minimize(){
        if(visibleProperties){
            visibleProperties = false;
            setPreferredSize(new Dimension(preferredWidth,preferredMinHeight));
            setSize(preferredWidth,preferredMinHeight);
        }
        else {
            visibleProperties = true;
            setPreferredSize(new Dimension(preferredWidth,preferredHeight));
            setSize(preferredWidth,preferredHeight);
        }
    }
    
    jfMainFrame getMainFrame(){
        JPanel jp = this;
        JLayeredPane jlp0 = (JLayeredPane)jp.getParent();
        JPanel jp0 = (JPanel)jlp0.getParent();
        JLayeredPane jlp1 = (JLayeredPane)jp0.getParent();
        JRootPane jrp = (JRootPane)jlp1.getParent();
        jfMainFrame jfm = (jfMainFrame)jrp.getParent();
        return jfm;
    }
    JLayeredPane getLayeredPane(){
        JPanel jp = this;
        JLayeredPane jlp0 = (JLayeredPane)jp.getParent();
        return jlp0;
    }
    
    Point getInPort() {
        return new Point(getLocation().x-10,getLocation().y+15);
    }
    
    Point getOutPort(){
        return new Point(getLocation().x+10+getWidth(),getLocation().y+15);
    }
    
    void frontify(){
        JLayeredPane jlp = (JLayeredPane)this.getParent();
        jlp.moveToFront(this);
        jlp.repaint();
    }
    public void mousePressed(MouseEvent e) {
        EntityPanel ep = (EntityPanel)e.getSource();
        JLayeredPane jlp = (JLayeredPane)ep.getParent();
        jlp.moveToFront(ep);
    }
    public void mouseReleased(MouseEvent e){
    }
    public void mouseEntered(MouseEvent e){
    }
    public void mouseExited(MouseEvent e){
    }
    public void mouseClicked(MouseEvent e){
        if(e.getClickCount() == 2) {
            if(this instanceof AbilityPanel || this instanceof BuffPanel) {
                if(SwingUtilities.isRightMouseButton(e)) {
                    String input = "";
                    while(input.equals(""))
                    {
                        String type = "";
                        if(this instanceof AbilityPanel)
                            type = "Ability";
                        else
                            type = "Buff";
                        input = JOptionPane.showInputDialog("Please select a new name for " + type + title.getText());
                        if(input == null)
                            return;
                        
                    }                        
                    String oldName = title.getText();
                    if(input.indexOf("\"") == 0 && input.lastIndexOf("\"") == input.length()-1)
                        input = input.substring(1,input.length()-1);
                    attachedEntity.name = input;
                    title.setText(input);
                    for(int i = 0; i < parents.size(); i++) {
                        EntityPanel curPar = parents.get(i);
                        for(int j = 0; j < curPar.virtualList.size(); j++) {
                            Property curProp = curPar.virtualList.get(j);
                            if(curProp.getValue().equals("\"" + oldName + "\"")) {
                                curProp.overwrite("\"" + input + "\"");
                                curPar.populate(curPar.propertyData);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }


    public void attachLineage() {
        Entity e = attachedEntity;
        //System.err.println("Entity: " + e.name);
        //System.err.println("  PropCount: " + e.props.size());
        for(int i = 0; i < virtualList.size(); i++) {
            Property p = virtualList.get(i);
            //System.err.println("\tProperty: " + p.getName());
            if(p.getType() == Property.BUFF) {
                //System.err.println("\t\tBuff");
                String val = p.getValue();
                val = val.substring(1);
                val = val.substring(0,val.length()-1);
                for(int j = 0; j < getMainFrame().buffList.size(); j++) {
                    Buff compare = getMainFrame().buffList.get(j);
                    if(val.equals(compare.name)) {
                        compare.ownerPanel.parents.add(this);
                        children.add(compare.ownerPanel);
                        compare.ownerPanel.attachLineage();
                        break;
                    }
                }
            }
        }
        for(int i = 0; i < children.size(); i++) {
            children.get(i).attachLineage();
        }
    }
}
